package org.light.framework.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 反射工具类
 * @author de.cel
 *
 */
public class ReflectionUtil {

	public static Object newInstance(Class<?> cls) {

		Object instance = null;
		try {
			instance = cls.newInstance();
		} catch (Exception e) {
			System.out.println("newInstance失败，" + e);
		}
		return instance;
	}

	public static Object invokeMethod(Object obj, Method method, Object... args) {
		Object result = null;
		try {

			method.setAccessible(true);
			result = method.invoke(obj, args);
		} catch (Exception e) {
			System.out.println("invokeMethod失败，" + e);
		}
		return result;
	}

	public static void setField(Object obj, Field field, Object value) {
		try {
			field.setAccessible(true);
			field.set(obj, value);
		} catch (Exception e) {
			System.out.println("setField失败，" + e);
		}
	}

	/**
	 * 获取属性值
	 * 
	 * @param model
	 * @param pName
	 * @return
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 */
	public static <T> Object getPropertyValue(T model, String pName) throws NoSuchFieldException, SecurityException {
		if (model == null || StringUtil.isNullOrEmpty(pName))
			return null;

		Object value = null;
		String[] pNames = pName.split("\\.");
		int length = pNames.length;

		// 取系统类型属性值，形如：model.Name
		if (length == 1) {
			Field property = model.getClass().getDeclaredField(pName);
			if (property != null) {
				try {
					// 取BillURL("//UploadFiles//" + this.Organization.ID +
					// "//Bill//" + this.ID + ".png" )这类属性会报错
					value = property.get(model);
				} catch (Exception ex) {
					// String path =
					// WebHelper.CurContext.Server.MapPath("~/reflectionHelper.error");
					// TextHelper.AppendString(path, String.Format("========{0}
					// 方法名：GetPropertyValue 类名：{1} 属性名：{2} 对象:{3} ",
					// DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), typeof(T),
					// property.Name, model));
					return null;
				}
			}
		} // 取自定义类型属性值，形如：model.Customer.Name 、model.Customer.Bank.Code
		else {
			Object p = model;
			Object pLast = p;
			String pNameLast = pName.split("\\.")[length - 1];

			for (int i = 0; i < length - 1; i++) {
				String pNameTemp = pNames[i];
				// 不导出集合类型属性，形如：model.Details，如需要，请单独导出
				if (!pNameTemp.contains("[0]")) {
					p = getPropertyValue(p, pNameTemp);
					pLast = p;
				}
			}
			value = getPropertyValue(pLast, pNameLast);
		}
		return value;
	}

	/**
	 * 设置对象的属性值
	 * 
	 * @param model
	 * @param values
	 *            属性-值键值对
	 * @return
	 * @throws Exception
	 */
	public static Object setPropertyValue(Object model, Map<String, Object> values) throws Exception {

		try {
			for (String propertyName : values.keySet()) {
				setPropertyValue(model, propertyName, values.get(propertyName));
			}
		} catch (Exception e) {

			System.out.println(e);
		}

		return model;
	}

	/**
	 * 设置属性值
	 * 
	 * @param model
	 * @param pName
	 * @param value
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static void setPropertyValue(Object model, String pName, Object value) throws Exception {

		if (model == null || StringUtil.isNullOrEmpty(pName))
			return;

		String[] pNames = pName.split("\\.");
		int length = pNames.length;

		if (length > 1) // 为自定义类型属性赋值， 形如：model.Customer.Name
						// 、model.Customer.Bank.Code
		{

			Object p = model;
			Object pLast = p;
			String pNameLast = pName.split("\\.")[length - 1];

			for (int i = 0; i < length - 1; i++) {
				String pNameTemp = pNames[i];

				if (pNameTemp.contains("[0]"))// 集合类型属性
				{
					p = pLast = getPropertyValue(pLast, pNameTemp.split("[")[0]);
				} else {
					p = tryGetPropertyValue(p, pNameTemp);
					setPropertyValue(pLast, pNameTemp, p);
					pLast = p;
				}
			}
			setPropertyValue(pLast, pNameLast, value);
		} else {
			Field property = model.getClass().getDeclaredField(pName);
			if (property != null && value != null) {
				property.setAccessible(true);
				
				Object realValue=StringUtil.convert(value, property.getType());
				property.set(model, realValue);
				
			} else if (model instanceof List && model.getClass().getGenericInterfaces().length > 0) {
				@SuppressWarnings("rawtypes")
				List list = (List) model;
				java.lang.reflect.Type genericType = model.getClass().getGenericInterfaces()[0];

				Object item = null;

				if (list.size() > 0 && list.get(0) != null) {
					item = list.get(0);
				} else {
					Class<?> c = genericType.getClass();
					item = c.newInstance();
					list.add(item);
				}
				setPropertyValue(item, pName, value);
			}
		}
	}

	/**
	 * 尝试获取对象的属性值，如果对象为空，则new一个
	 * 
	 * @param model
	 * @param propertyName
	 * @return
	 * @throws NoSuchFieldException
	 * @throws SecurityException
	 * @throws InstantiationException
	 * @throws IllegalAccessException
	 */
	public static Object tryGetPropertyValue(Object model, String propertyName)
			throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException {
		Field property = null;
		Object pValue = null;
		if (model instanceof List) // && model.GetType().IsGenericType)
		{
			List<?> list = (List<?>) model;
			if (!list.isEmpty()) {
				property = list.get(0).getClass().getDeclaredField(propertyName);
				pValue = getPropertyValue(list.get(0), propertyName);
			}
		} else {
			property = model.getClass().getDeclaredField(propertyName);
			pValue = getPropertyValue(model, propertyName);
		}

		if (pValue == null) {
			pValue = property.getType().newInstance();
			property.setAccessible(true);
			property.set(model, pValue);
		}
		return pValue;
	}
}
